//https://gitee.com/adonin/lunargz
import { XL0, XL0_xzb, XL1, nutB, dt_at } from './lunargz-base';

export default function Lunargz(time) {
        let t = new Date(time).getTime();
        if (isNaN(t)) throw '输入时间不正确'
        this.time = t;
        return this.init();
}

Lunargz.prototype = {
    rad: 180 * 3600 / Math.PI, //每弧度的角秒数
    pi2: Math.PI * 2,
    cs_rEar: 6378.1366, //地球赤道半径(千米)
    cs_k: 0.2725076, //月亮与地球的半径比(用于半影计算)
    cs_sMoon: () => { return this.cs_k * this.cs_rEar * 1.0000036 * this.rad }, //用于月亮视半径计算
    J2000: 2451545,
    init() {
        this.ssqinit();
        return this.gzTime()
    },
    gzTime() {
        //时间转换成干支
        var now = this.Format(this.time, "YYYY:MM:DD:HH:mm:ss").split(":")
        let lunar = this.yueLiCalc(Number(now[0]), Number(now[1]));
        var day = lunar.lun[Number(now[2]) - 1];
        var gztime = {};
        // gztime['lun'] = lunar.lun;
        gztime['jq'] = lunar.yjd;
        gztime['time'] = now;
        gztime['week'] = this.tranweek(day.week);
        gztime['lunar'] = [day.Lyear2, day.Lmc, day.Ldc, this.tranday(Number(now[3]))];
        // gztime['gz'] = [lunar.ly,day.lmc,day.ldc,this.tranday(Number(now[3]))];
        gztime['gz'] = [day.Lyear2, day.Lmonth2, day.Lday2];
        //如果现在是23点-00点，推后一天
        if (Number(now[3]) >= 23) {
            var now2 = this.Format(this.time + 24 * 60 * 60 * 1000, "YYYY:MM:DD:HH:mm:ss").split(":");
            var lunar2 = this.yueLiCalc(Number(now2[0]), Number(now2[1]));
            var day2 = lunar2.lun[Number(now2[2]) - 1];
            gztime['lunar'][2] = day2.Ldc;
            gztime['gz'][2] = day2.Lday2;
            gztime['lunar'][3] = this.tranday(Number(now2[3]))
        }
        //如果当天是节气分界日；判断相应的时分是否已经分月
        if (day.jqmc && day.jqmc == lunar.yjd[0].jq) {
            // console.log("节气分界日", day.jqsj)
            var ntime = new Date(now[0] + "-" + now[1] + "-" + now[2] + " " + day.jqsj).valueOf();
            //如果当天是节气分界日,没有到分界时间，上移一月
            if (this.time < ntime) {
                gztime['gz'][1] = lunar.lun[Number(now[2] - 2)].Lmonth2;
                if (day.jqmc == '立春') {
                    //如果当天是年分界日,没有到分界时间，上移一年
                    gztime['gz'][0] = lunar.lun[Number(now[2] - 2)].Lyear2;
                    gztime['lunar'][0] = lunar.lun[Number(now[2] - 2)].Lyear2;
                }
            }
        }
        //获取本月时间起止
        var jqt = new Date(lunar.yjd[0].time).valueOf();
        if (this.time >= jqt) {
            //如果时间大于此节，取下一节时间
            var next = this.Format(this.time + this._getday(now, 1) * 24 * 60 * 60 * 1000, "YYYY:MM:DD:HH:mm:ss").split(":");
            var nextlunar = this.yueLiCalc(Number(next[0]), Number(next[1]));
            jqt = new Date(nextlunar.yjd[0].time).valueOf();
            gztime['jq'][1] = nextlunar.yjd[0];
        } else if (this.time < jqt) {
            //如果时间小于此节，取上一节时间
            var last = this.Format(this.time - this._getday(now, 0) * 24 * 60 * 60 * 1000, "YYYY:MM:DD:HH:mm:ss").split(":");
            var lastlunar = this.yueLiCalc(Number(last[0]), Number(last[1]));
            gztime['jq'][1] = gztime['jq'][0];
            gztime['jq'][0] = lastlunar.yjd[0];
        }
        var ylunar1 = this.yueLiCalc(Number(now[0]), 2);
        gztime['yjq'] = ylunar1.yjd;
        var ylunar2 = this.yueLiCalc(Number(now[0]) + 1, 2);
        gztime['yjq'][1] = ylunar2.yjd[0];
        var yg = gztime['gz'][2].substring(0, 1);
        gztime['gz'][3] = this.trantg(yg, gztime['lunar'][3]);
        return gztime
    },
    _getday(time, q) {
        if (q) {
            if (time[2] > 20) {
                return 15;
            } else return 28;
        } else {
            if (time[2] > 20) {
                return 40;
            } else return 28;
        }
    },
    tranweek: function(w) {
        switch (w) {
            case 0:
                return '星期日';
            case 1:
                return '星期一';
            case 2:
                return '星期二';
            case 3:
                return '星期三';
            case 4:
                return '星期四';
            case 5:
                return '星期五';
            case 6:
                return '星期六';
        }
    },
    tranday: function(t) {

        if (t >= 23 || t < 1) {
            return '子';
        } else if (t >= 1 && t < 3) {
            return '丑';
        } else if (t >= 3 && t < 5) {
            return '寅';
        } else if (t >= 5 && t < 7) {
            return '卯';
        } else if (t >= 7 && t < 9) {
            return '辰';
        } else if (t >= 9 && t < 11) {
            return '巳';
        } else if (t >= 11 && t < 13) {
            return '午';
        } else if (t >= 13 && t < 15) {
            return '未';
        } else if (t >= 15 && t < 17) {
            return '申';
        } else if (t >= 17 && t < 19) {
            return '酉';
        } else if (t >= 19 && t < 21) {
            return '戌';
        } else if (t >= 21 && t < 23) {
            return '亥';
        }
    },
    trantg: function(t, d) {
        //返回时辰干支，t为月干,d为日支
        var ti;
        var di = this.obb.Zhi.indexOf(d);
        if (t == '甲' || t == '己') {
            ti = this.obb.Gan.indexOf("甲");
        } else if (t == '乙' || t == '庚') {
            ti = this.obb.Gan.indexOf("丙");
        } else if (t == '丙' || t == '辛') {
            ti = this.obb.Gan.indexOf("戊");
        } else if (t == '丁' || t == '壬') {
            ti = this.obb.Gan.indexOf("庚");
        } else if (t == '戊' || t == '癸') {
            ti = this.obb.Gan.indexOf("壬");
        }
        var tti = (di + ti > 9 ? di + ti - 10 : di + ti);

        return this.obb.Gan[tti] + d;
    },
    //返回公历某一个月的'公农回'三合历
    yueLiCalc(By, Bm) {
        var i0;
        var lun = new Array();
        for (i0 = 0; i0 < 31; i0++) lun[i0] = new Object();
        lun.dn = 0;

        var i, j, c, Bd0, Bdn;
        //日历物件初始化
        this._JD.h = 12, this._JD.m = 0, this._JD.s = 0.1;
        this._JD.Y = By;
        this._JD.M = Bm;
        this._JD.D = 1;
        Bd0 = this.int2(this.toJD()) - this.J2000; //公历月首,中午
        this._JD.M++;
        if (this._JD.M > 12) this._JD.Y++, this._JD.M = 1;
        Bdn = this.int2(this.toJD()) - this.J2000 - Bd0; //本月天数(公历)
        this.w0 = (Bd0 + this.J2000 + 1 + 7000000) % 7; //本月第一天的星期
        this.y = By; //公历年份
        this.m = Bm; //公历月分
        this.d0 = Bd0;
        this.dn = Bdn;

        //所属公历年对应的农历干支纪年
        c = By - 1984 + 12000;
        this.Ly = this.obb.Gan[c % 10] + this.obb.Zhi[c % 12]; //干支纪年
        this.ShX = this.obb.ShX[c % 12]; //该年对应的生肖
        var D, w, ob, ob2;
        //提取各日信息
        var yjd = [];
        for (i = 0, j = 0; i < Bdn; i++) {
            ob = lun[i];
            ob.d0 = Bd0 + i; //儒略日,北京时12:00
            ob.di = i; //公历月内日序数
            ob.y = By; //公历年
            ob.m = Bm; //公历月
            ob.dn = Bdn; //公历月天数
            ob.week0 = this.w0; //月首的星期
            ob.week = (this.w0 + i) % 7; //当前日的星期
            ob.weeki = this.int2((this.w0 + i) / 7); //本日所在的周序号
            ob.weekN = this.int2((this.w0 + Bdn - 1) / 7) + 1; //本月的总周数
            this.setFromJD(ob.d0 + this.J2000);
            ob.d = this._JD.D; //公历日名称

            //农历月历
            if (!this.SSQ.ZQ.length || ob.d0 < this.SSQ.ZQ[0] || ob.d0 >= this.SSQ.ZQ[24]) //如果d0已在计算农历范围内则不再计算
                this.calcY(ob.d0);
            var mk = this.int2((ob.d0 - this.SSQ.HS[0]) / 30);
            if (mk < 13 && this.SSQ.HS[mk + 1] <= ob.d0) mk++; //农历所在月的序数

            ob.Ldi = ob.d0 - this.SSQ.HS[mk]; //距农历月首的编移量,0对应初一
            ob.Ldc = this.obb.rmc[ob.Ldi]; //农历日名称
            ob.cur_dz = ob.d0 - this.SSQ.ZQ[0]; //距冬至的天数
            ob.cur_xz = ob.d0 - this.SSQ.ZQ[12]; //距夏至的天数
            ob.cur_lq = ob.d0 - this.SSQ.ZQ[15]; //距立秋的天数
            ob.cur_mz = ob.d0 - this.SSQ.ZQ[11]; //距芒种的天数
            ob.cur_xs = ob.d0 - this.SSQ.ZQ[13]; //距小暑的天数
            if (ob.d0 == this.SSQ.HS[mk] || ob.d0 == Bd0) { //月的信息
                ob.Lmc = this.SSQ.ym[mk]; //月名称
                ob.Ldn = this.SSQ.dx[mk]; //月大小
                ob.Lleap = (this.SSQ.leap && this.SSQ.leap == mk) ? '闰' : ''; //闰状况
                ob.Lmc2 = mk < 13 ? this.SSQ.ym[mk + 1] : "未知"; //下个月名称,判断除夕时要用到
            } else {
                ob2 = lun[i - 1];
                ob.Lmc = ob2.Lmc, ob.Ldn = ob2.Ldn;
                ob.Lleap = ob2.Lleap, ob.Lmc2 = ob2.Lmc2;
            }
            var qk = this.int2((ob.d0 - this.SSQ.ZQ[0] - 7) / 15.2184);
            if (qk < 23 && ob.d0 >= this.SSQ.ZQ[qk + 1]) qk++; //节气的取值范围是0-23
            if (ob.d0 == this.SSQ.ZQ[qk]) ob.Ljq = this.obb.jqmc[qk];
            else ob.Ljq = '';

            ob.yxmc = ob.yxjd = ob.yxsj = ''; //月相名称,月相时刻(儒略日),月相时间串
            ob.jqmc = ob.jqjd = ob.jqsj = ''; //定气名称,节气时刻(儒略日),节气时间串

            //干支纪年处理
            //以立春为界定年首
            D = this.SSQ.ZQ[3] + (ob.d0 < this.SSQ.ZQ[3] ? -365 : 0) + 365.25 * 16 - 35; //以立春为界定纪年
            ob.Lyear = Math.floor(D / 365.2422 + 0.5); //农历纪年(10进制,1984年起算)
            //以下几行以正月初一定年首
            D = this.SSQ.HS[2]; //一般第3个月为春节
            for (j = 0; j < 14; j++) { //找春节
                if (this.SSQ.ym[j] != '正' || this.SSQ.leap == j && j) continue;
                D = this.SSQ.HS[j];
                if (ob.d0 < D) { D -= 365; break; } //无需再找下一个正月
            }
            D = D + 5810; //计算该年春节与1984年平均春节(立春附近)相差天数估计
            ob.Lyear0 = Math.floor(D / 365.2422 + 0.5); //农历纪年(10进制,1984年起算)

            D = ob.Lyear + 12000;
            ob.Lyear2 = this.obb.Gan[D % 10] + this.obb.Zhi[D % 12]; //干支纪年(立春)
            D = ob.Lyear0 + 12000;
            ob.Lyear3 = this.obb.Gan[D % 10] + this.obb.Zhi[D % 12]; //干支纪年(正月)
            ob.Lyear4 = ob.Lyear0 + 1984 + 2698; //黄帝纪年


            //纪月处理,1998年12月7(大雪)开始连续进行节气计数,0为甲子
            mk = this.int2((ob.d0 - this.SSQ.ZQ[0]) / 30.43685);
            if (mk < 12 && ob.d0 >= this.SSQ.ZQ[2 * mk + 1]) mk++; //相对大雪的月数计算,mk的取值范围0-12

            D = mk + this.int2((this.SSQ.ZQ[12] + 390) / 365.2422) * 12 + 900000; //相对于1998年12月7(大雪)的月数,900000为正数基数
            ob.Lmonth = D % 12;
            ob.Lmonth2 = this.obb.Gan[D % 10] + this.obb.Zhi[D % 12];

            //纪日,2000年1月7日起算
            D = ob.d0 - 6 + 9000000;
            ob.Lday2 = this.obb.Gan[D % 10] + this.obb.Zhi[D % 12];

            //星座
            mk = this.int2((ob.d0 - this.SSQ.ZQ[0] - 15) / 30.43685);
            if (mk < 11 && ob.d0 >= this.SSQ.ZQ[2 * mk + 2]) mk++; //星座所在月的序数,(如果j=13,ob.d0不会超过第14号中气)
            ob.XiZ = this.obb.XiZ[(mk + 12) % 12] + '座';
            //节日
            ob.A = ob.B = ob.C = '';
            ob.Fjia = 0;
        }

        //以下是月相与节气的处理
        var d, xn, jd2 = Bd0 + this.dt_T(Bd0) - 8 / 24;
        //月相查找
        w = this.MS_aLon(jd2 / 36525, 10, 3);
        w = this.int2((w - 0.78) / Math.PI * 2) * Math.PI / 2;
        do {
            d = this.so_accurate(w);
            D = this.int2(d + 0.5);
            xn = this.int2(w / this.pi2 * 4 + 4000000.01) % 4;
            w += this.pi2 / 4;
            if (D >= Bd0 + Bdn) break;
            if (D < Bd0) continue;
            ob = lun[D - Bd0];
            ob.yxmc = this.obb.yxmc[xn]; //取得月相名称
            ob.yxjd = d;
            ob.yxsj = this.timeStr(d);
        } while (D + 5 < Bd0 + Bdn);

        //节气查找
        w = this.S_aLon(jd2 / 36525, 3);
        w = this.int2((w - 0.13) / this.pi2 * 24) * this.pi2 / 24;
        do {
            d = this.qi_accurate(w);
            D = this.int2(d + 0.5);
            xn = this.int2(w / this.pi2 * 24 + 24000006.01) % 24;
            w += this.pi2 / 24;
            if (D >= Bd0 + Bdn) break;
            if (D < Bd0) continue;
            ob = lun[D - Bd0];
            ob.jqmc = this.obb.jqmc[xn]; //取得节气名称
            ob.jqjd = d;
            ob.jqsj = this.timeStr(d);
            yjd.push({
                time: ob.y + "-" + ob.m + "-" + ob.d + " " + ob.jqsj,
                jq: ob.jqmc
            })
        } while (D + 12 < Bd0 + Bdn);

        return {
            lun,
            yjd
        }
    },
    substr2(s, n, end) { //截串(网页设计对过长的文字做截处理)
        s = s.replace(/(^\s*)|(\s*$)/g, "");
        if (s.length > n + 1) return s.substr(0, n) + end;
        return s;
    },
    int2(v) { return Math.floor(v); }, //取整数部分

    XL0_calc(xt, zn, t, n) { //xt星体,zn坐标号,t儒略世纪数,n计算项数
        t /= 10; //转为儒略千年数
        var i, j, v = 0,
            tn = 1,
            c;
        var F = XL0[xt],
            n1, n2, N;
        var n0, pn = zn * 6 + 1,
            N0 = F[pn + 1] - F[pn]; //N0序列总数
        for (i = 0; i < 6; i++, tn *= t) {
            n1 = F[pn + i], n2 = F[pn + 1 + i], n0 = n2 - n1;
            if (!n0) continue;
            if (n < 0) N = n2; //确定项数
            else { N = this.int2(3 * n * n0 / N0 + 0.5) + n1; if (i) N += 3; if (N > n2) N = n2; }
            for (j = n1, c = 0; j < N; j += 3) c += F[j] * Math.cos(F[j + 1] + t * F[j + 2]);
            v += c * tn;
        }
        v /= F[0];
        if (xt == 0) { //地球
            var t2 = t * t,
                t3 = t2 * t; //千年数的各次方
            if (zn == 0) v += (-0.0728 - 2.7702 * t - 1.1019 * t2 - 0.0996 * t3) / this.rad;
            if (zn == 1) v += (+0.0000 + 0.0004 * t + 0.0004 * t2 - 0.0026 * t3) / this.rad;
            if (zn == 2) v += (-0.0020 + 0.0044 * t + 0.0213 * t2 - 0.0250 * t3) / 1000000;
        } else { //其它行星
            var dv = XL0_xzb[(xt - 1) * 3 + zn];
            if (zn == 0) v += -3 * t / this.rad;
            if (zn == 2) v += dv / 1000000;
            else v += dv / this.rad;
        }
        return v;
    },
    gxc_moonLon() { return -3.4E-6; }, //月球经度光行差,误差0.07"
    gxc_sunLon(t) { //太阳光行差,t是世纪数
        var v = -0.043126 + 628.301955 * t - 0.000002732 * t * t; //平近点角
        var e = 0.016708634 - 0.000042037 * t - 0.0000001267 * t * t;
        return (-20.49552 * (1 + e * Math.cos(v))) / this.rad; //黄经光行差
    },
    nutationLon2(t) { //只计算黄经章动
        var i, a, t2 = t * t,
            dL = 0,
            B = nutB;
        for (i = 0; i < B.length; i += 5) {
            if (i == 0) a = -1.742 * t;
            else a = 0;
            dL += (B[i + 3] + a) * Math.sin(B[i] + B[i + 1] * t + B[i + 2] * t2);
        }
        return dL / 100 / this.rad;
    },
    XL1_calc(zn, t, n) { //计算月亮
        var ob = XL1[zn];
        var i, j, F, N, v = 0,
            tn = 1,
            c;
        var t2 = t * t,
            t3 = t2 * t,
            t4 = t3 * t,
            t5 = t4 * t,
            tx = t - 10;
        if (zn == 0) {
            v += (3.81034409 + 8399.684730072 * t - 3.319e-05 * t2 + 3.11e-08 * t3 - 2.033e-10 * t4) * this.rad; //月球平黄经(弧度)
            v += 5028.792262 * t + 1.1124406 * t2 + 0.00007699 * t3 - 0.000023479 * t4 - 0.0000000178 * t5; //岁差(角秒)
            if (tx > 0) v += -0.866 + 1.43 * tx + 0.054 * tx * tx; //对公元3000年至公元5000年的拟合,最大误差小于10角秒
        }
        t2 /= 1e4, t3 /= 1e8, t4 /= 1e8;
        n *= 6;
        if (n < 0) n = ob[0].length;
        for (i = 0; i < ob.length; i++, tn *= t) {
            F = ob[i];
            N = this.int2(n * F.length / ob[0].length + 0.5);
            if (i) N += 6;
            if (N >= F.length) N = F.length;
            for (j = 0, c = 0; j < N; j += 6) c += F[j] * Math.cos(F[j + 1] + t * F[j + 2] + t2 * F[j + 3] + t3 * F[j + 4] + t4 * F[j + 5]);
            v += c * tn;
        }
        if (zn != 2) v /= this.rad;
        return v;
    },
    dt_ext(y, jsd) { var dy = (y - 1820) / 100; return -20 + jsd * dy * dy; }, //二次曲线外推
    dt_calc(y) { //计算世界时与原子时之差,传入年

        var y0 = dt_at[dt_at.length - 2]; //表中最后一年
        var t0 = dt_at[dt_at.length - 1]; //表中最后一年的deltatT
        if (y >= y0) {
            var jsd = 31; //sjd是y1年之后的加速度估计。瑞士星历表jsd=31,NASA网站jsd=32,skmap的jsd=29
            if (y > y0 + 100) return this.dt_ext(y, jsd);
            var v = this.dt_ext(y, jsd); //二次曲线外推
            var dv = this.dt_ext(y0, jsd) - t0; //ye年的二次外推与te的差

            return v - dv * (y0 + 100 - y) / 100;
        }
        var i, d = dt_at;

        for (i = 0; i < d.length; i += 5)
            if (y < d[i + 5]) break;
        var t1 = (y - d[i]) / (d[i + 5] - d[i]) * 10,
            t2 = t1 * t1,
            t3 = t2 * t1;
        return d[i + 1] + d[i + 2] * t1 + d[i + 3] * t2 + d[i + 4] * t3;
    },
    dt_T(t) { return this.dt_calc(t / 365.2425 + 2000) / 86400.0; }, //传入儒略日(this.J2000起算),计算TD-UT(单位:日)
    Format: function(time, fmt) {
        //时间转换
        var Time = new Date(time);
        var o = {
            "M+": Time.getMonth() + 1, //月份 
            "D+": Time.getDate(), //日 
            "H+": Time.getHours(), //小时 
            "m+": Time.getMinutes(), //分 
            "s+": Time.getSeconds(), //秒 
            "q+": Math.floor((Time.getMonth() + 3) / 3), //季度 
            "S": Time.getMilliseconds() //毫秒 
        };
        if (/(Y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (Time.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        return fmt;
    },


    obb: {
        //农历基础构件
        //private私有成员定义
        //public公有成员定义
        //以下几个是公有只读数据
        numCn: new Array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'), //中文数字
        Gan: new Array("甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"),
        Zhi: new Array("子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"),
        ShX: new Array("鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"),
        XiZ: new Array('摩羯', '水瓶', '双鱼', '白羊', '金牛', '双子', '巨蟹', '狮子', '处女', '天秤', '天蝎', '射手'),
        yxmc: new Array("朔", "上弦", "望", "下弦"), //月相名称表
        jqmc: new Array('冬至', '小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪'),
        ymc: new Array('十一', '十二', '正', '二', '三', '四', '五', '六', '七', '八', '九', '十'), //月名称,建寅
        rmc: new Array('初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十', '卅一'),

    },
    qi_accurate(W) { var t = this.S_aLon_t(W) * 36525; return t - this.dt_T(t) + 8 / 24; }, //精气
    so_accurate(W) {

        var t = this.MS_aLon_t(W) * 36525;
        return t - this.dt_T(t) + 8 / 24;
    }, //精朔
    qi_accurate2(jd) { //精气
        var d = Math.PI / 12;
        var w = Math.floor((jd + 293) / 365.2422 * 24) * d;
        var a = this.qi_accurate(w);
        if (a - jd > 5) return this.qi_accurate(w - d);
        if (a - jd < -5) return this.qi_accurate(w + d);
        return a;
    },
    so_accurate2(jd) { return this.so_accurate(Math.floor((jd + 8) / 29.5306) * Math.PI * 2); } //精朔
    ,
    SSQ: { //实朔实气计算器
        //private成员定义
        SB: '', //朔修正表
        QB: '', //气修正表
        suoKB: new Array( //朔直线拟合参数
            1457698.231017, 29.53067166, // -721-12-17 h=0.00032 古历·春秋
            1546082.512234, 29.53085106, // -479-12-11 h=0.00053 古历·战国
            1640640.735300, 29.53060000, // -221-10-31 h=0.01010 古历·秦汉
            1642472.151543, 29.53085439, // -216-11-04 h=0.00040 古历·秦汉

            1683430.509300, 29.53086148, // -104-12-25 h=0.00313 汉书·律历志(太初历)平气平朔
            1752148.041079, 29.53085097, //   85-02-13 h=0.00049 后汉书·律历志(四分历)
            1807665.420323, 29.53059851, //  237-02-12 h=0.00033 晋书·律历志(景初历)
            1883618.114100, 29.53060000, //  445-01-24 h=0.00030 宋书·律历志(何承天元嘉历)
            1907360.704700, 29.53060000, //  510-01-26 h=0.00030 宋书·律历志(祖冲之大明历)
            1936596.224900, 29.53060000, //  590-02-10 h=0.01010 随书·律历志(开皇历)
            1939135.675300, 29.53060000, //  597-01-24 h=0.00890 随书·律历志(大业历)
            1947168.00 //  619-01-21
        ),

        qiKB: new Array( //气直线拟合参数
            1640650.479938, 15.21842500, // -221-11-09 h=0.01709 古历·秦汉
            1642476.703182, 15.21874996, // -216-11-09 h=0.01557 古历·秦汉

            1683430.515601, 15.218750011, // -104-12-25 h=0.01560 汉书·律历志(太初历)平气平朔 回归年=365.25000
            1752157.640664, 15.218749978, //   85-02-23 h=0.01559 后汉书·律历志(四分历) 回归年=365.25000
            1807675.003759, 15.218620279, //  237-02-22 h=0.00010 晋书·律历志(景初历) 回归年=365.24689
            1883627.765182, 15.218612292, //  445-02-03 h=0.00026 宋书·律历志(何承天元嘉历) 回归年=365.24670
            1907369.128100, 15.218449176, //  510-02-03 h=0.00027 宋书·律历志(祖冲之大明历) 回归年=365.24278
            1936603.140413, 15.218425000, //  590-02-17 h=0.00149 随书·律历志(开皇历) 回归年=365.24220
            1939145.524180, 15.218466998, //  597-02-03 h=0.00121 随书·律历志(大业历) 回归年=365.24321
            1947180.798300, 15.218524844, //  619-02-03 h=0.00052 新唐书·历志(戊寅元历)平气定朔 回归年=365.24460
            1964362.041824, 15.218533526, //  666-02-17 h=0.00059 新唐书·历志(麟德历) 回归年=365.24480
            1987372.340971, 15.218513908, //  729-02-16 h=0.00096 新唐书·历志(大衍历,至德历) 回归年=365.24433
            1999653.819126, 15.218530782, //  762-10-03 h=0.00093 新唐书·历志(五纪历) 回归年=365.24474
            2007445.469786, 15.218535181, //  784-02-01 h=0.00059 新唐书·历志(正元历,观象历) 回归年=365.24484
            2021324.917146, 15.218526248, //  822-02-01 h=0.00022 新唐书·历志(宣明历) 回归年=365.24463
            2047257.232342, 15.218519654, //  893-01-31 h=0.00015 新唐书·历志(崇玄历) 回归年=365.24447
            2070282.898213, 15.218425000, //  956-02-16 h=0.00149 旧五代·历志(钦天历) 回归年=365.24220
            2073204.872850, 15.218515221, //  964-02-16 h=0.00166 宋史·律历志(应天历) 回归年=365.24437
            2080144.500926, 15.218530782, //  983-02-16 h=0.00093 宋史·律历志(乾元历) 回归年=365.24474
            2086703.688963, 15.218523776, // 1001-01-31 h=0.00067 宋史·律历志(仪天历,崇天历) 回归年=365.24457
            2110033.182763, 15.218425000, // 1064-12-15 h=0.00669 宋史·律历志(明天历) 回归年=365.24220
            2111190.300888, 15.218425000, // 1068-02-15 h=0.00149 宋史·律历志(崇天历) 回归年=365.24220
            2113731.271005, 15.218515671, // 1075-01-30 h=0.00038 李锐补修(奉元历) 回归年=365.24438
            2120670.840263, 15.218425000, // 1094-01-30 h=0.00149 宋史·律历志 回归年=365.24220
            2123973.309063, 15.218425000, // 1103-02-14 h=0.00669 李锐补修(占天历) 回归年=365.24220
            2125068.997336, 15.218477932, // 1106-02-14 h=0.00056 宋史·律历志(纪元历) 回归年=365.24347
            2136026.312633, 15.218472436, // 1136-02-14 h=0.00088 宋史·律历志(统元历,乾道历,淳熙历) 回归年=365.24334
            2156099.495538, 15.218425000, // 1191-01-29 h=0.00149 宋史·律历志(会元历) 回归年=365.24220
            2159021.324663, 15.218425000, // 1199-01-29 h=0.00149 宋史·律历志(统天历) 回归年=365.24220
            2162308.575254, 15.218461742, // 1208-01-30 h=0.00146 宋史·律历志(开禧历) 回归年=365.24308
            2178485.706538, 15.218425000, // 1252-05-15 h=0.04606 淳祐历 回归年=365.24220
            2178759.662849, 15.218445786, // 1253-02-13 h=0.00231 会天历 回归年=365.24270
            2185334.020800, 15.218425000, // 1271-02-13 h=0.00520 宋史·律历志(成天历) 回归年=365.24220
            2187525.481425, 15.218425000, // 1277-02-12 h=0.00520 本天历 回归年=365.24220
            2188621.191481, 15.218437494, // 1280-02-13 h=0.00015 元史·历志(郭守敬授时历) 回归年=365.24250
            2322147.76 // 1645-09-21
        ),
        //排月序(生成实际年历),在调用calcY()后得到以下数据
        //时间系统全部使用北京时，即使是天象时刻的输出，也是使用北京时
        //如果天象的输出不使用北京时，会造成显示混乱，更严重的是无法与古历比对
        leap: 0, //闰月位置
        ym: new Array(), //各月名称
        ZQ: new Array(), //中气表,其中.liqiu是节气立秋的儒略日,计算三伏时用到
        HS: new Array(), //合朔表
        dx: new Array(), //各月大小
        Yn: new Array(), //年计数
    },
    calcY(jd) { //农历排月序计算,可定出农历,有效范围：两个冬至之间(冬至一 <= d < 冬至二)
        var A = this.SSQ.ZQ,
            B = this.SSQ.HS; //中气表,日月合朔表(整日)
        var i, W, w;

        //该年的气
        W = this.int2((jd - 355 + 183) / 365.2422) * 365.2422 + 355; //355是2000.12冬至,得到较靠近jd的冬至估计值
        if (this.calc(W, '气') > jd) W -= 365.2422;
        for (i = 0; i < 25; i++) A[i] = this.calc(W + 15.2184 * i, '气'); //25个节气时刻(北京时间),从冬至开始到下一个冬至以后
        A.pe1 = this.calc(W - 15.2, '气');
        A.pe2 = this.calc(W - 30.4, '气'); //补算二气,确保一年中所有月份的“气”全部被计算在内

        //今年"首朔"的日月黄经差w
        w = this.calc(A[0], '朔'); //求较靠近冬至的朔日
        if (w > A[0]) w -= 29.53;

        //该年所有朔,包含14个月的始末
        for (i = 0; i < 15; i++) B[i] = this.calc(w + 29.5306 * i, '朔');

        //月大小
        this.SSQ.leap = 0;
        for (i = 0; i < 14; i++) {
            this.SSQ.dx[i] = this.SSQ.HS[i + 1] - this.SSQ.HS[i]; //月大小
            this.SSQ.ym[i] = i; //月序初始化
        }


        //-721年至-104年的后九月及月建问题,与朔有关，与气无关
        var YY = this.int2((this.SSQ.ZQ[0] + 10 + 180) / 365.2422) + 2000; //确定年份
        if (YY >= -721 && YY <= -104) {
            var ns = new Array(),
                yy;
            for (i = 0; i < 3; i++) {
                yy = YY + i - 1;
                //颁行历年首, 闰月名称, 月建
                if (yy >= -721) ns[i] = this.calc(1457698 - this.J2000 + this.int2(0.342 + (yy + 721) * 12.368422) * 29.5306, '朔'), ns[i + 3] = '十三', ns[i + 6] = 2; //春秋历,ly为-722.12.17
                if (yy >= -479) ns[i] = this.calc(1546083 - this.J2000 + this.int2(0.500 + (yy + 479) * 12.368422) * 29.5306, '朔'), ns[i + 3] = '十三', ns[i + 6] = 2; //战国历,ly为-480.12.11
                if (yy >= -220) ns[i] = this.calc(1640641 - this.J2000 + this.int2(0.866 + (yy + 220) * 12.369000) * 29.5306, '朔'), ns[i + 3] = '后九', ns[i + 6] = 11; //秦汉历,ly为-221.10.31
            }
            var nn, f1;
            for (i = 0; i < 14; i++) {
                for (nn = 2; nn >= 0; nn--)
                    if (this.SSQ.HS[i] >= ns[nn]) break;
                f1 = this.int2((this.SSQ.HS[i] - ns[nn] + 15) / 29.5306); //该月积数
                if (f1 < 12) this.SSQ.ym[i] = this.obb.ymc[(f1 + ns[nn + 6]) % 12];
                else this.SSQ.ym[i] = ns[nn + 3];
            }
            return;
        }


        //无中气置闰法确定闰月,(气朔结合法,数据源需有冬至开始的的气和朔)
        if (B[13] <= A[24]) { //第13月的月末没有超过冬至(不含冬至),说明今年含有13个月
            for (i = 1; B[i + 1] > A[2 * i] && i < 13; i++); //在13个月中找第1个没有中气的月份
            this.SSQ.leap = i;
            for (; i < 14; i++) this.SSQ.ym[i]--;
        }

        //名称转换(月建别名)
        for (i = 0; i < 14; i++) {
            var Dm = this.SSQ.HS[i] + this.J2000,
                v2 = this.SSQ.ym[i]; //Dm初一的儒略日,v2为月建序号
            var mc = this.obb.ymc[v2 % 12]; //月建对应的默认月名称：建子十一,建丑十二,建寅为正……
            if (Dm >= 1724360 && Dm <= 1729794) mc = this.obb.ymc[(v2 + 1) % 12]; //  8.01.15至 23.12.02 建子为十二,其它顺推
            else if (Dm >= 1807724 && Dm <= 1808699) mc = this.obb.ymc[(v2 + 1) % 12]; //237.04.12至239.12.13 建子为十二,其它顺推
            else if (Dm >= 1999349 && Dm <= 1999467) mc = this.obb.ymc[(v2 + 2) % 12]; //761.12.02至762.03.30 建子为正月,其它顺推
            else if (Dm >= 1973067 && Dm <= 1977052) { if (v2 % 12 == 0) mc = "正"; if (v2 == 2) mc = '一'; } //689.12.18至700.11.15 建子为正月,建寅为一月,其它不变

            if (Dm == 1729794 || Dm == 1808699) mc = '拾贰'; //239.12.13及23.12.02均为十二月,为避免两个连续十二月，此处改名

            this.SSQ.ym[i] = mc;
        }
    },
    so_low(W) { //低精度定朔计算,在2000年至600，误差在2小时以内(仍比古代日历精准很多)
        var v = 7771.37714500204;
        var t = (W + 1.08472) / v;
        t -= (-0.0000331 * t * t +
                0.10976 * Math.cos(0.785 + 8328.6914 * t) +
                0.02224 * Math.cos(0.187 + 7214.0629 * t) -
                0.03342 * Math.cos(4.669 + 628.3076 * t)) / v +
            (32 * (t + 1.8) * (t + 1.8) - 20) / 86400 / 36525;
        return t * 36525 + 8 / 24;
    },
    qi_low(W) { //最大误差小于30分钟，平均5分
        var t, L, v = 628.3319653318;
        t = (W - 4.895062166) / v; //第一次估算,误差2天以内
        t -= (53 * t * t + 334116 * Math.cos(4.67 + 628.307585 * t) + 2061 * Math.cos(2.678 + 628.3076 * t) * t) / v / 10000000; //第二次估算,误差2小时以内

        L = 48950621.66 + 6283319653.318 * t + 53 * t * t //平黄经
            +
            334166 * Math.cos(4.669257 + 628.307585 * t) //地球椭圆轨道级数展开
            +
            3489 * Math.cos(4.6261 + 1256.61517 * t) //地球椭圆轨道级数展开
            +
            2060.6 * Math.cos(2.67823 + 628.307585 * t) * t //一次泊松项
            -
            994 - 834 * Math.sin(2.1824 - 33.75705 * t); //光行差与章动修正

        t -= (L / 10000000 - W) / 628.332 + (32 * (t + 1.8) * (t + 1.8) - 20) / 86400 / 36525;
        return t * 36525 + 8 / 24;
    },
    qi_high(W) { //较高精度气
        var t = this.S_aLon_t2(W) * 36525;
        t = t - this.dt_T(t) + 8 / 24;
        var v = ((t + 0.5) % 1) * 86400;
        if (v < 1200 || v > 86400 - 1200) t = this.S_aLon_t(W) * 36525 - this.dt_T(t) + 8 / 24;
        return t;
    },
    so_high(W) { //较高精度朔
        var t = this.MS_aLon_t2(W) * 36525;
        t = t - this.dt_T(t) + 8 / 24;
        var v = ((t + 0.5) % 1) * 86400;
        if (v < 1800 || v > 86400 - 1800) t = this.MS_aLon_t(W) * 36525 - this.dt_T(t) + 8 / 24;
        return t;
    },

    jieya(s) { //气朔解压缩
        var o = "0000000000",
            o2 = o + o;
        s = s.replace(/J/g, '00');
        s = s.replace(/I/g, '000');
        s = s.replace(/H/g, '0000');
        s = s.replace(/G/g, '00000');
        s = s.replace(/t/g, '02');
        s = s.replace(/s/g, '002');
        s = s.replace(/r/g, '0002');
        s = s.replace(/q/g, '00002');
        s = s.replace(/p/g, '000002');
        s = s.replace(/o/g, '0000002');
        s = s.replace(/n/g, '00000002');
        s = s.replace(/m/g, '000000002');
        s = s.replace(/l/g, '0000000002');
        s = s.replace(/k/g, '01');
        s = s.replace(/j/g, '0101');
        s = s.replace(/i/g, '001');
        s = s.replace(/h/g, '001001');
        s = s.replace(/g/g, '0001');
        s = s.replace(/f/g, '00001');
        s = s.replace(/e/g, '000001');
        s = s.replace(/d/g, '0000001');
        s = s.replace(/c/g, '00000001');
        s = s.replace(/b/g, '000000001');
        s = s.replace(/a/g, '0000000001');
        s = s.replace(/A/g, o2 + o2 + o2);
        s = s.replace(/B/g, o2 + o2 + o);
        s = s.replace(/C/g, o2 + o2);
        s = s.replace(/D/g, o2 + o);
        s = s.replace(/E/g, o2);
        s = s.replace(/F/g, o);
        return s;
    },
    ssqinit() { //初使用化
        var suoS, qiS;
        //  619-01-21开始16598个朔日修正表 d0=1947168
        suoS = "EqoFscDcrFpmEsF2DfFideFelFpFfFfFiaipqti1ksttikptikqckstekqttgkqttgkqteksttikptikq2fjstgjqttjkqttgkqt";
        suoS += "ekstfkptikq2tijstgjiFkirFsAeACoFsiDaDiADc1AFbBfgdfikijFifegF1FhaikgFag1E2btaieeibggiffdeigFfqDfaiBkF";
        suoS += "1kEaikhkigeidhhdiegcFfakF1ggkidbiaedksaFffckekidhhdhdikcikiakicjF1deedFhFccgicdekgiFbiaikcfi1kbFibef";
        suoS += "gEgFdcFkFeFkdcfkF1kfkcickEiFkDacFiEfbiaejcFfffkhkdgkaiei1ehigikhdFikfckF1dhhdikcfgjikhfjicjicgiehdik";
        suoS += "cikggcifgiejF1jkieFhegikggcikFegiegkfjebhigikggcikdgkaFkijcfkcikfkcifikiggkaeeigefkcdfcfkhkdgkegieid";
        suoS += "hijcFfakhfgeidieidiegikhfkfckfcjbdehdikggikgkfkicjicjF1dbidikFiggcifgiejkiegkigcdiegfggcikdbgfgefjF1";
        suoS += "kfegikggcikdgFkeeijcfkcikfkekcikdgkabhkFikaffcfkhkdgkegbiaekfkiakicjhfgqdq2fkiakgkfkhfkfcjiekgFebicg";
        suoS += "gbedF1jikejbbbiakgbgkacgiejkijjgigfiakggfggcibFifjefjF1kfekdgjcibFeFkijcfkfhkfkeaieigekgbhkfikidfcje";
        suoS += "aibgekgdkiffiffkiakF1jhbakgdki1dj1ikfkicjicjieeFkgdkicggkighdF1jfgkgfgbdkicggfggkidFkiekgijkeigfiski";
        suoS += "ggfaidheigF1jekijcikickiggkidhhdbgcfkFikikhkigeidieFikggikhkffaffijhidhhakgdkhkijF1kiakF1kfheakgdkif";
        suoS += "iggkigicjiejkieedikgdfcggkigieeiejfgkgkigbgikicggkiaideeijkefjeijikhkiggkiaidheigcikaikffikijgkiahi1";
        suoS += "hhdikgjfifaakekighie1hiaikggikhkffakicjhiahaikggikhkijF1kfejfeFhidikggiffiggkigicjiekgieeigikggiffig";
        suoS += "gkidheigkgfjkeigiegikifiggkidhedeijcfkFikikhkiggkidhh1ehigcikaffkhkiggkidhh1hhigikekfiFkFikcidhh1hit";
        suoS += "cikggikhkfkicjicghiediaikggikhkijbjfejfeFhaikggifikiggkigiejkikgkgieeigikggiffiggkigieeigekijcijikgg";
        suoS += "ifikiggkideedeijkefkfckikhkiggkidhh1ehijcikaffkhkiggkidhh1hhigikhkikFikfckcidhh1hiaikgjikhfjicjicgie";
        suoS += "hdikcikggifikigiejfejkieFhegikggifikiggfghigkfjeijkhigikggifikiggkigieeijcijcikfksikifikiggkidehdeij";
        suoS += "cfdckikhkiggkhghh1ehijikifffffkhsFngErD1pAfBoDd1BlEtFqA2AqoEpDqElAEsEeB2BmADlDkqBtC1FnEpDqnEmFsFsAFn";
        suoS += "llBbFmDsDiCtDmAB2BmtCgpEplCpAEiBiEoFqFtEqsDcCnFtADnFlEgdkEgmEtEsCtDmADqFtAFrAtEcCqAE1BoFqC1F1DrFtBmF";
        suoS += "tAC2ACnFaoCgADcADcCcFfoFtDlAFgmFqBq2bpEoAEmkqnEeCtAE1bAEqgDfFfCrgEcBrACfAAABqAAB1AAClEnFeCtCgAADqDoB";
        suoS += "mtAAACbFiAAADsEtBqAB2FsDqpFqEmFsCeDtFlCeDtoEpClEqAAFrAFoCgFmFsFqEnAEcCqFeCtFtEnAEeFtAAEkFnErAABbFkAD";
        suoS += "nAAeCtFeAfBoAEpFtAABtFqAApDcCGJ";

        //1645-09-23开始7567个节气修正表
        qiS = "FrcFs22AFsckF2tsDtFqEtF1posFdFgiFseFtmelpsEfhkF2anmelpFlF1ikrotcnEqEq2FfqmcDsrFor22FgFrcgDscFs22FgEe";
        qiS += "FtE2sfFs22sCoEsaF2tsD1FpeE2eFsssEciFsFnmelpFcFhkF2tcnEqEpFgkrotcnEqrEtFermcDsrE222FgBmcmr22DaEfnaF22";
        qiS += "2sD1FpeForeF2tssEfiFpEoeFssD1iFstEqFppDgFstcnEqEpFg11FscnEqrAoAF2ClAEsDmDtCtBaDlAFbAEpAAAAAD2FgBiBqo";
        qiS += "BbnBaBoAAAAAAAEgDqAdBqAFrBaBoACdAAf1AACgAAAeBbCamDgEifAE2AABa1C1BgFdiAAACoCeE1ADiEifDaAEqAAFe1AcFbcA";
        qiS += "AAAAF1iFaAAACpACmFmAAAAAAAACrDaAAADG0";

        this.SSQ.SB = this.jieya(suoS); //定朔修正表解压
        this.SSQ.QB = this.jieya(qiS); //定气修正表解压
    },

    //public公有成员定义
    calc(jd, qs) { //jd应靠近所要取得的气朔日,qs='气'时，算节气的儒略日
        jd += 2451545;
        var i, D, n;
        var B = this.SSQ.suoKB,
            pc = 14;
        if (qs == '气') B = this.SSQ.qiKB, pc = 7;
        var f1 = B[0] - pc,
            f2 = B[B.length - 1] - pc,
            f3 = 2436935;

        if (jd < f1 || jd >= f3) { //平气朔表中首个之前，使用现代天文算法。1960.1.1以后，使用现代天文算法 (这一部分调用了qi_high和so_high,所以需星历表支持)
            if (qs == '气') return Math.floor(this.qi_high(Math.floor((jd + pc - 2451259) / 365.2422 * 24) * Math.PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算
            else return Math.floor(this.so_high(Math.floor((jd + pc - 2451551) / 29.5306) * Math.PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算
        }

        if (jd >= f1 && jd < f2) { //平气或平朔
            for (i = 0; i < B.length; i += 2)
                if (jd + pc < B[i + 2]) break;
            D = B[i] + B[i + 1] * Math.floor((jd + pc - B[i]) / B[i + 1]);
            D = Math.floor(D + 0.5);
            if (D == 1683460) D++; //如果使用太初历计算-103年1月24日的朔日,结果得到的是23日,这里修正为24日(实历)。修正后仍不影响-103的无中置闰。如果使用秦汉历，得到的是24日，本行D不会被执行。
            return D - 2451545;
        }

        if (jd >= f2 && jd < f3) { //定气或定朔
            if (qs == '气') {
                D = Math.floor(this.qi_low(Math.floor((jd + pc - 2451259) / 365.2422 * 24) * Math.PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算
                n = this.SSQ.QB.substr(Math.floor((jd - f2) / 365.2422 * 24), 1); //找定气修正值
            } else {
                D = Math.floor(this.so_low(Math.floor((jd + pc - 2451551) / 29.5306) * Math.PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算
                n = this.SSQ.SB.substr(Math.floor((jd - f2) / 29.5306), 1); //找定朔修正值
            }
            if (n == "1") return D + 1;
            if (n == "2") return D - 1;
            return D;
        }
    },

    _JD: { //日期元件
        Y: 2000,
        M: 1,
        D: 1,
        h: 12,
        m: 0,
        s: 0,
        //星期相关
        Weeks: new Array('日', '一', '二', '三', '四', '五', '六', '七'),
    },
    JD(y, m, d) { //公历转儒略日
        var n = 0,
            G = 0;
        if (y * 372 + m * 31 + this.int2(d) >= 588829) G = 1; //判断是否为格里高利历日1582*372+10*31+15
        if (m <= 2) m += 12, y--;
        if (G) n = this.int2(y / 100), n = 2 - n + this.int2(n / 4); //加百年闰
        return this.int2(365.25 * (y + 4716)) + this.int2(30.6001 * (m + 1)) + d + n - 1524.5;
    },
    DD(jd) { //儒略日数转公历
        var r = new Object();
        var D = this.int2(jd + 0.5),
            F = jd + 0.5 - D,
            c; //取得日数的整数部份A及小数部分F
        if (D >= 2299161) c = this.int2((D - 1867216.25) / 36524.25), D += 1 + c - this.int2(c / 4);
        D += 1524;
        r['Y'] = this.int2((D - 122.1) / 365.25); //年数
        D -= this.int2(365.25 * r['Y']);
        r['M'] = this.int2(D / 30.601); //月数
        D -= this.int2(30.601 * r['M']);
        r['D'] = D; //日数
        if (r['M'] > 13) r['M'] -= 13, r['Y'] -= 4715;
        else r['M'] -= 1, r['Y'] -= 4716;
        //日的小数转为时分秒
        F *= 24;
        r['h'] = this.int2(F);
        F -= r['h'];
        F *= 60;
        r['m'] = this.int2(F);
        F -= r['m'];
        F *= 60;
        r['s'] = F;
        return r;
    },
    DD2str(r) { //日期转为串
        var Y = "     " + r.Y,
            M = "0" + r.M,
            D = "0" + r.D;
        var h = r.h,
            m = r.m,
            s = this.int2(r.s + .5);
        if (s >= 60) s -= 60, m++;
        if (m >= 60) m -= 60, h++;
        h = "0" + h;
        m = "0" + m;
        s = "0" + s;
        Y = Y.substr(Y.length - 5, 5);
        M = M.substr(M.length - 2, 2);
        D = D.substr(D.length - 2, 2);
        h = h.substr(h.length - 2, 2);
        m = m.substr(m.length - 2, 2);
        s = s.substr(s.length - 2, 2);
        return Y + "-" + M + "-" + D + " " + h + ":" + m + ":" + s;
    },
    JD2str(jd) { //this.JD转为串
        var r = this.DD(jd);
        return this.DD2str(r);
    },
    toJD() { return this.JD(this._JD.Y, this._JD.M, this._JD.D + ((this._JD.s / 60 + this._JD.m) / 60 + this._JD.h) / 24); }, //公历转儒略日
    setFromJD(jd) {
        var r = this.DD(jd);
        this._JD.Y = r.Y, this._JD.M = r.M, this._JD.D = r.D, this._JD.m = r.m, this._JD.h = r.h, this._JD.s = r.s;
    }, //儒略日数转公历

    timeStr(jd) { //提取jd中的时间(去除日期)
        var h, m, s;
        jd += 0.5;
        jd = (jd - this.int2(jd));
        s = this.int2(jd * 86400 + 0.5);
        h = this.int2(s / 3600);
        s -= h * 3600;
        m = this.int2(s / 60);
        s -= m * 60;
        h = "0" + h;
        m = "0" + m;
        s = "0" + s;
        return h.substr(h.length - 2, 2) + ':' + m.substr(m.length - 2, 2) + ':' + s.substr(s.length - 2, 2);
    },
    getWeek(jd) { return this.int2(jd + 1.5 + 7000000) % 7; }, //星期计算
    nnweek(y, m, n, w) { //求y年m月的第n个星期w的儒略日数
        var jd = this.JD(y, m, 1.5); //月首儒略日
        var w0 = (jd + 1 + 7000000) % 7; //月首的星期
        var r = jd - w0 + 7 * n + w; //jd-w0+7*n是和n个星期0,起算下本月第一行的星期日(可能落在上一月)。加w后为第n个星期w
        if (w >= w0) r -= 7; //第1个星期w可能落在上个月,造成多算1周,所以考虑减1周
        if (n == 5) {
            m++;
            if (m > 12) m = 1, y++; //下个月
            if (r >= this.JD(y, m, 1.5)) r -= 7; //r跑到下个月则减1周
        }
        return r;
    },


    //物件this.XL : 日月黄道平分点坐标、视坐标、速度、已知经度反求时间等方面的计算
    //日月星历基本函数类
    //=====================
    //星历函数(日月球面坐标计算)
    E_Lon(t, n) { return this.XL0_calc(0, 0, t, n); }, //地球经度计算,返回Date分点黄经,传入世纪数、取项数
    M_Lon(t, n) { return this.XL1_calc(0, t, n); }, //月球经度计算,返回Date分点黄经,传入世纪数,n是项数比例
    //=========================
    E_v(t) { //地球速度,t是世纪数,误差小于万分3
        var f = 628.307585 * t;
        return 628.332 + 21 * Math.sin(1.527 + f) + 0.44 * Math.sin(1.48 + f * 2) +
            0.129 * Math.sin(5.82 + f) * t + 0.00055 * Math.sin(4.21 + f) * t * t;
    },
    M_v(t) { //月球速度计算,传入世经数
        var v = 8399.71 - 914 * Math.sin(0.7848 + 8328.691425 * t + 0.0001523 * t * t); //误差小于5%
        v -= 179 * Math.sin(2.543 + 15542.7543 * t) //误差小于0.3%
            +
            160 * Math.sin(0.1874 + 7214.0629 * t) +
            62 * Math.sin(3.14 + 16657.3828 * t) +
            34 * Math.sin(4.827 + 16866.9323 * t) +
            22 * Math.sin(4.9 + 23871.4457 * t) +
            12 * Math.sin(2.59 + 14914.4523 * t) +
            7 * Math.sin(0.23 + 6585.7609 * t) +
            5 * Math.sin(0.9 + 25195.624 * t) +
            5 * Math.sin(2.32 - 7700.3895 * t) +
            5 * Math.sin(3.88 + 8956.9934 * t) +
            5 * Math.sin(0.49 + 7771.3771 * t);
        return v;
    },

    //=========================
    MS_aLon(t, Mn, Sn) { //月日视黄经的差值
        return this.M_Lon(t, Mn) + this.gxc_moonLon(t) - (this.E_Lon(t, Sn) + this.gxc_sunLon(t) + Math.PI);
    },
    S_aLon(t, n) { //太阳视黄经
        return this.E_Lon(t, n) + this.nutationLon2(t) + this.gxc_sunLon(t) + Math.PI; //注意，这里的章动计算很耗时
    },

    //=========================

    E_Lon_t(W) { //已知地球真黄经求时间
        var t, v = 628.3319653318;
        t = (W - 1.75347) / v;
        v = this.E_v(t); //v的精度0.03%，详见原文
        t += (W - this.E_Lon(t, 10)) / v;
        v = this.E_v(t); //再算一次v有助于提高精度,不算也可以
        t += (W - this.E_Lon(t, -1)) / v;
        return t;
    },
    M_Lon_t(W) { //已知真月球黄经求时间
        var t, v = 8399.70911033384;
        t = (W - 3.81034) / v;
        t += (W - this.M_Lon(t, 3)) / v;
        v = this.M_v(t); //v的精度0.5%，详见原文
        t += (W - this.M_Lon(t, 20)) / v;
        t += (W - this.M_Lon(t, -1)) / v;
        return t;
    },
    MS_aLon_t(W) { //已知月日视黄经差求时间
        var t, v = 7771.37714500204;
        t = (W + 1.08472) / v;
        t += (W - this.MS_aLon(t, 3, 3)) / v;
        v = this.M_v(t) - this.E_v(t); //v的精度0.5%，详见原文
        t += (W - this.MS_aLon(t, 20, 10)) / v;
        t += (W - this.MS_aLon(t, -1, 60)) / v;
        return t;
    },
    S_aLon_t(W) { //已知太阳视黄经反求时间
        var t, v = 628.3319653318;
        t = (W - 1.75347 - Math.PI) / v;
        v = this.E_v(t); //v的精度0.03%，详见原文
        t += (W - this.S_aLon(t, 10)) / v;
        v = this.E_v(t); //再算一次v有助于提高精度,不算也可以
        t += (W - this.S_aLon(t, -1)) / v;
        return t;
    },
    /****
    MS_aLon_t1:function(W){ //已知月日视黄经差求时间,高速低精度,误差不超过40秒
      var t,v = 7771.37714500204;
      t  = ( W + 1.08472               )/v;
      t += ( W - this.MS_aLon(t, 3, 3) )/v;  v=this.M_v(t)-this.E_v(t);  //v的精度0.5%，详见原文
      t += ( W - this.MS_aLon(t,50,20) )/v;
      return t;
    },
    S_aLon_t1:function(W){ //已知太阳视黄经反求时间,高速低精度,最大误差不超过50秒,平均误差15秒
      var t,v= 628.3319653318;
      t  = ( W - 1.75347-Math.PI   )/v; v = 628.332 + 21*Math.sin( 1.527+628.307585*t );
      t += ( W - this.S_aLon(t,3) )/v;
      t += ( W - this.S_aLon(t,40))/v;
      return t;
    },
    ****/
    MS_aLon_t2(W) { //已知月日视黄经差求时间,高速低精度,误差不超过600秒(只验算了几千年)
        var t, v = 7771.37714500204;
        t = (W + 1.08472) / v;
        var L, t2 = t * t;
        t -= (-0.00003309 * t2 + 0.10976 * Math.cos(0.784758 + 8328.6914246 * t + 0.000152292 * t2) + 0.02224 * Math.cos(0.18740 + 7214.0628654 * t - 0.00021848 * t2) - 0.03342 * Math.cos(4.669257 + 628.307585 * t)) / v;
        L = this.M_Lon(t, 20) - (4.8950632 + 628.3319653318 * t + 0.000005297 * t * t + 0.0334166 * Math.cos(4.669257 + 628.307585 * t) + 0.0002061 * Math.cos(2.67823 + 628.307585 * t) * t + 0.000349 * Math.cos(4.6261 + 1256.61517 * t) - 20.5 / this.rad);
        v = 7771.38 - 914 * Math.sin(0.7848 + 8328.691425 * t + 0.0001523 * t * t) - 179 * Math.sin(2.543 + 15542.7543 * t) - 160 * Math.sin(0.1874 + 7214.0629 * t);
        t += (W - L) / v;
        return t;
    },
    S_aLon_t2(W) { //已知太阳视黄经反求时间,高速低精度,最大误差不超过600秒
        var t, v = 628.3319653318;
        t = (W - 1.75347 - Math.PI) / v;
        t -= (0.000005297 * t * t + 0.0334166 * Math.cos(4.669257 + 628.307585 * t) + 0.0002061 * Math.cos(2.67823 + 628.307585 * t) * t) / v;
        t += (W - this.E_Lon(t, 8) - Math.PI + (20.5 + 17.2 * Math.sin(2.1824 - 33.75705 * t)) / this.rad) / v;
        return t;
    },
    moonIll(t) { //月亮被照亮部分的比例
        var t2 = t * t,
            t3 = t2 * t,
            t4 = t3 * t;
        var D, M, m, a, dm = Math.PI / 180;
        D = (297.8502042 + 445267.1115168 * t - 0.0016300 * t2 + t3 / 545868 - t4 / 113065000) * dm; //日月平距角
        M = (357.5291092 + 35999.0502909 * t - 0.0001536 * t2 + t3 / 24490000) * dm; //太阳平近点
        m = (134.9634114 + 477198.8676313 * t + 0.0089970 * t2 + t3 / 69699 - t4 / 14712000) * dm; //月亮平近点
        a = Math.PI - D + (-6.289 * Math.sin(m) + 2.100 * Math.sin(M) - 1.274 * Math.sin(D * 2 - m) - 0.658 * Math.sin(D * 2) - 0.214 * Math.sin(m * 2) - 0.110 * Math.sin(D)) * dm;
        return (1 + Math.cos(a)) / 2;
    },
    moonRad(r, h) { //转入地平纬度及地月质心距离,返回站心视半径(角秒)
        return this.cs_sMoon() / r * (1 + Math.sin(h) * this.cs_rEar / r);
    },

    moonMinR(t, min) { //求月亮近点时间和距离,t为儒略世纪数力学时
        var a = 27.55454988 / 36525,
            b;
        if (min) b = -10.3302 / 36525;
        else b = 3.4471 / 36525;
        t = b + a * this.int2((t - b) / a + 0.5); //平近(远)点时间
        var r1, r2, r3, dt;
        //初算二次
        dt = 1 / 36525;
        r1 = this.XL1_calc(2, t - dt, 10);
        r2 = this.XL1_calc(2, t, 10);
        r3 = this.XL1_calc(2, t + dt, 10);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2;
        dt = 0.5 / 36525;
        r1 = this.XL1_calc(2, t - dt, 20);
        r2 = this.XL1_calc(2, t, 20);
        r3 = this.XL1_calc(2, t + dt, 20);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2;
        //精算
        dt = 1200 / 86400 / 36525;
        r1 = this.XL1_calc(2, t - dt, -1);
        r2 = this.XL1_calc(2, t, -1);
        r3 = this.XL1_calc(2, t + dt, -1);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2;
        r2 += (r1 - r3) / (r1 + r3 - 2 * r2) * (r3 - r1) / 8;
        var re = new Array(t, r2);
        return re;
    },
    moonNode(t, asc) { //月亮升交点
        var a = 27.21222082 / 36525,
            b;
        if (asc) b = 21 / 36525;
        else b = 35 / 36525;
        t = b + a * this.int2((t - b) / a + 0.5); //平升(降)交点时间
        var w, v, w2, dt;
        dt = 0.5 / 36525;
        w = this.XL1_calc(1, t, 10);
        w2 = this.XL1_calc(1, t + dt, 10);
        v = (w2 - w) / dt;
        t -= w / v;
        dt = 0.05 / 36525;
        w = this.XL1_calc(1, t, 40);
        w2 = this.XL1_calc(1, t + dt, 40);
        v = (w2 - w) / dt;
        t -= w / v;
        w = this.XL1_calc(1, t, -1);
        t -= w / v;
        var re = new Array(t, this.XL1_calc(0, t, -1));
        return re;
    },
    earthMinR(t, min) { //地球近远点
        var a = 365.25963586 / 36525,
            b;
        if (min) b = 1.7 / 36525;
        else b = 184.5 / 36525;
        t = b + a * this.int2((t - b) / a + 0.5); //平近(远)点时间
        var r1, r2, r3, dt;
        //初算二次
        dt = 3 / 36525;
        r1 = this.XL0_calc(0, 2, t - dt, 10);
        r2 = this.XL0_calc(0, 2, t, 10);
        r3 = this.XL0_calc(0, 2, t + dt, 10);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2; //误差几个小时
        dt = 0.2 / 36525;
        r1 = this.XL0_calc(0, 2, t - dt, 80);
        r2 = this.XL0_calc(0, 2, t, 80);
        r3 = this.XL0_calc(0, 2, t + dt, 80);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2; //误差几分钟
        //精算
        dt = 0.01 / 36525;
        r1 = this.XL0_calc(0, 2, t - dt, -1);
        r2 = this.XL0_calc(0, 2, t, -1);
        r3 = this.XL0_calc(0, 2, t + dt, -1);
        t += (r1 - r3) / (r1 + r3 - 2 * r2) * dt / 2; //误差小于秒
        r2 += (r1 - r3) / (r1 + r3 - 2 * r2) * (r3 - r1) / 8;
        var re = new Array(t, r2);
        return re;

    },
}